/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.repair.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.repair.entity.*;
import org.springblade.modules.repair.enums.MaintainPlanContentEnum;
import org.springblade.modules.repair.enums.SignEnum;
import org.springblade.modules.repair.enums.SignErrorTypeEnum;
import org.springblade.modules.repair.enums.WxArriveStatusEnums;
import org.springblade.modules.repair.mapper.MaintainPlanContentUserMapper;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.utils.DateUtils;
import org.springblade.modules.repair.vo.MaintainPlanContentUserVO;
import org.springblade.modules.repair.vo.PlanUserVO;
import org.springblade.modules.repair.vo.plan.v2.PlanUserSignDetailVo;
import org.springblade.modules.repair.vo.plan.v2.SignStatusInfoVo;
import org.springblade.modules.repair.vo.plan.wx.PlanMaintainUserVO;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 维保任务关联人员中间表 服务实现类
 *
 * @author BladeX
 * @since 2021-05-21
 */
@Slf4j
@Service
public class MaintainPlanContentUserServiceImpl extends BaseServiceImpl<MaintainPlanContentUserMapper, MaintainPlanContentUser> implements IMaintainPlanContentUserService {

	@Lazy
	@Autowired
	private IUserService userService;
	@Lazy
	@Autowired
	private IMaintainSignService signService;
	@Autowired
	private MaintainPlanContentPersonnelService planContentPersonnelService;
	@Lazy
	@Autowired
	private MaintainPlanUserDayCountService planUserDayCountService;
	@Lazy
	@Autowired
	IMaintainPlanContentService maintainPlanContentService;

	/**
	 * 签到签退状态1:正常,其它异常
	 */
	private final int SING_STATUS = 2;

	@Override
	public IPage<MaintainPlanContentUserVO> selectMaintainPlanContentUserPage(IPage<MaintainPlanContentUserVO> page, MaintainPlanContentUserVO maintainPlanContentUser) {
		return page.setRecords(baseMapper.selectMaintainPlanContentUserPage(page, maintainPlanContentUser));
	}

	@Override
	public List<PlanUserVO> listUserByPlanId(Long planId) {
		return baseMapper.listUserByPlanId(planId);
	}

	@Override
	public void updatePlanUserSignInfo(Long planId, Integer signType, Long userId, Integer signStatus) {

		log.info("=========================== updatePlanUserSignInfo : planId: {},signType: {},userId: {},signStatus: {} ==============================", planId, signType, userId, signStatus);

		List<MaintainPlanContentUser> list = this.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));

		log.info("=========================== updatePlanUserSignInfo : select planContentUserList: {} ==============================", list);
		MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(planId);
		for (MaintainPlanContentUser maintainPlanContentUser : list) {
			//设置维修的预警状态
			if (maintainPlanContentUser.getUserId().equals(userId)) {
				if (maintainPlanContentUser.getSignDate() == null) {
					maintainPlanContentUser.setSignDate(new Date());
				}
				if (maintainPlanContent.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_WX.getId()) {
					if (maintainPlanContentUser.getPlanArriveDate() != null) {
						if (Convert.toInt(maintainPlanContentUser.getWxArriveStatus(), -1) != WxArriveStatusEnums.ARRIVE_ON_TIME.getId() && Convert.toInt(maintainPlanContentUser.getWxArriveStatus(), -1) != WxArriveStatusEnums.DIS_ARRIVE_ON_TIME.getId()) {
							if (System.currentTimeMillis() <= maintainPlanContentUser.getPlanArriveDate().getTime()) {
								maintainPlanContentUser.setWxArriveStatus(WxArriveStatusEnums.ARRIVE_ON_TIME.getId());
							} else {
								maintainPlanContentUser.setWxArriveStatus(WxArriveStatusEnums.DIS_ARRIVE_ON_TIME.getId());
							}
						}
					}
				}
			}
			String realName = userService.getById(maintainPlanContentUser.getUserId()).getRealName();
			String signStatusInfo = Convert.toStr(maintainPlanContentUser.getSignStatusInfo(), "");
			if (StrUtil.isEmpty(signStatusInfo)) {
				SignStatusInfoVo signStatusInfoVo = new SignStatusInfoVo();
				signStatusInfoVo.setUserName(realName);
				if (signType == SignEnum.SIGN.getId()) {
					signStatusInfoVo.setSignStatus(signStatus);
					signStatusInfoVo.setSignOutStatus(signStatus);
				}
				signStatusInfo = JSON.toJSONString(signStatusInfoVo);
			} else {
				SignStatusInfoVo signStatusInfoVo = JSON.parseObject(signStatusInfo, SignStatusInfoVo.class);
				if (signType == SignEnum.SIGN.getId()) {
					if (signStatus == SING_STATUS) {
						signStatusInfoVo.setSignStatus(signStatus);
					}
				} else if (signType == SignEnum.SIGN_OUT.getId()) {
					if (signStatus == SING_STATUS) {
						signStatusInfoVo.setSignOutStatus(signStatus);
					}
				}
				signStatusInfo = JSON.toJSONString(signStatusInfoVo);
			}
			maintainPlanContentUser.setSignStatusInfo(signStatusInfo);


			PlanUserSignDetailVo planUserSignDetailVo = new PlanUserSignDetailVo();

			planUserSignDetailVo.setPlanId(planId);
			if (maintainPlanContentUser.getUserId().equals(userId)) {
				planUserSignDetailVo.setIsPlanStatus(signType == SignEnum.SIGN.getId() ? true : false);
				planUserSignDetailVo.setIsTakePartIn(true);
				planUserSignDetailVo.setUserName(realName);
				maintainPlanContentUser.setSignInfo(JSON.toJSONString(planUserSignDetailVo));
			} else {
				String signInfo = maintainPlanContentUser.getSignInfo();
				if (StrUtil.isEmpty(signInfo)) {
					planUserSignDetailVo.setIsPlanStatus(false);
					planUserSignDetailVo.setIsTakePartIn(false);
					planUserSignDetailVo.setUserName(realName);
					maintainPlanContentUser.setSignInfo(JSON.toJSONString(planUserSignDetailVo));
				}
			}

		}
		log.info("=========================== updatePlanUserSignInfo : update planContentUserList: {} ==============================", list);
		this.updateBatchById(list);
	}

	@Override
	public List<MaintainPlanContentUser> listUserByPlan(Long planId) {
		return baseMapper.listUserByPlan(planId);
	}

	@Override
	public List<String> listPlanUserDept(List<Long> userIds) {
		return baseMapper.listPlanUserDept(userIds);
	}

	@Override
	public boolean saveBatch(Long planId, List<Long> userIds, Date planArriveDate) {
		List<MaintainPlanContentUser> planContentUsers = this.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));
		if (planContentUsers.size() > 0) {
			List<Long> ids = planContentUsers.stream().map(MaintainPlanContentUser::getId).collect(Collectors.toList());
			this.removeByIds(ids);
		}
		List<MaintainPlanContentUser> saveList = new ArrayList<>(10);
		for (Long userId : userIds) {
			MaintainPlanContentUser maintainPlanContentUser = new MaintainPlanContentUser();
			maintainPlanContentUser.setUserId(userId);
			if (planArriveDate != null) {
				maintainPlanContentUser.setPlanArriveDate(new Date(DateUtils.getNowDateEnd(planArriveDate)));
			}
			maintainPlanContentUser.setPlanId(planId);
			saveList.add(maintainPlanContentUser);
		}
		this.saveBatch(saveList);
		return true;
	}

	@Override
	public String getPlanUserName(Long planId) {
		return baseMapper.getPlanUserName(planId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean changePlanUser(Long planId) {
		List<MaintainSign> signs = signService.list(Wrappers.<MaintainSign>lambdaQuery().eq(MaintainSign::getPlanId, planId));
		List<MaintainPlanContentUser> planContentUsers = this.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));
		List<Long> signUserIds = signs.stream().map(MaintainSign::getUserId).distinct().collect(Collectors.toList());
		// 计划作业人
		List<MaintainPlanContentPersonnel> personnelList = planContentUsers.stream().map(e -> {
			MaintainPlanContentPersonnel personnel = new MaintainPlanContentPersonnel();
			personnel.setPlanId(e.getPlanId());
			personnel.setUserId(e.getUserId());
			return personnel;
		}).collect(Collectors.toList());
		planContentPersonnelService.saveBatch(personnelList);
		// 计划未工作人id
		List<Long> users = planContentUsers.stream().map(MaintainPlanContentUser::getUserId).filter(e -> !signUserIds.contains(e)).collect(Collectors.toList());
		if (ObjectUtil.isNotEmpty(users)) {
			super.remove(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId).in(MaintainPlanContentUser::getUserId, users));
			planUserDayCountService.remove(Wrappers.<MaintainPlanUserDayCount>lambdaQuery().eq(MaintainPlanUserDayCount::getPlanId, planId).in(MaintainPlanUserDayCount::getUserId, users));
		}

		return Boolean.TRUE;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean changeAllPlanUser() {
		List<MaintainPlanContentUser> users = baseMapper.listAllByPlanner();
		List<MaintainPlanUserDayCount> userDayCounts = planUserDayCountService.listAllByPlanner();
		return super.removeByIds(users.stream().map(MaintainPlanContentUser::getId).collect(Collectors.toList()))
			&& planUserDayCountService.removeByIds(userDayCounts.stream().map(MaintainPlanUserDayCount::getId).collect(Collectors.toList()));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<MaintainPlanContentUser> updateRescuePlanUserSignInfo(Long planId) {

		List<MaintainPlanContentUser> list = super.list(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId));

		// 计划作业人
		List<MaintainPlanContentPersonnel> personnelList = list.stream().map(e -> {
			if (e.getSignUser() != null && e.getSignUser().getIsPlanStatus()) {
				this.updatePlanUserSignInfo(planId, SignEnum.SIGN_OUT.getId(), e.getUserId(), SignErrorTypeEnum.NORMAL.getId());
			}
			MaintainPlanContentPersonnel personnel = new MaintainPlanContentPersonnel();
			personnel.setPlanId(e.getPlanId());
			personnel.setUserId(e.getUserId());
			return personnel;
		}).collect(Collectors.toList());
		planContentPersonnelService.saveBatch(personnelList);

		// 计划未工作人id
		List<Long> users = list.stream().filter(e -> !e.getSignUser().getIsTakePartIn()).map(MaintainPlanContentUser::getUserId).collect(Collectors.toList());
		if (ObjectUtil.isNotEmpty(users)) {
			super.remove(Wrappers.<MaintainPlanContentUser>lambdaQuery().eq(MaintainPlanContentUser::getPlanId, planId).in(MaintainPlanContentUser::getUserId, users));
			planUserDayCountService.remove(Wrappers.<MaintainPlanUserDayCount>lambdaQuery().eq(MaintainPlanUserDayCount::getPlanId, planId).in(MaintainPlanUserDayCount::getUserId, users));
		}

		return list.stream().filter(e -> e.getSignUser().getIsTakePartIn()).collect(Collectors.toList());
	}

	@Override
	public MaintainPlanContentUser getLastPlanUser(Long planId, Long userId) {
		return baseMapper.getLastPlanUser(planId, userId);
	}

	@Override
	public void updateIsDeletedById(Long id, Integer isDeleted) {
		baseMapper.updateIsDeletedById(id, isDeleted);
	}

	@Override
	public List<MaintainPlanContentUser> listUserByPlanIds(List<Long> planIds) {
		return baseMapper.listUserByPlanIds(planIds);
	}

	@Override
	public List<PlanMaintainUserVO> selectWorkUsers(Long planId) {
		return baseMapper.selectWorkUsers(planId);
	}

}
